﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO.Ports;
using System.Threading;
using System.ComponentModel;
using System.Windows.Forms;

namespace clsLib_ActiveDevice
{
    public class TMR045 : ActiveDevice
    {
        SerialPort port;
        ICom icom;

        byte[] sendCommandContent;
        byte[] receiveCommandContent;

        public TMR045()
        {
            AppendCommandToDictionary();

            port = new SerialPort();

            icom = new ICom();
        }
        ~TMR045()
        {
            port.Dispose();
            icom.Dispose();
        }

        //-----------------------------------
        // ICom's parameter setter and getter.
        //-----------------------------------

        public class ICom : Component
        {
            int baudRate;
            public int BaudRate
            {
                get { return baudRate; }
                set { baudRate = value; }
            }
            int dataBits;
            public int DataBits
            {
                get { return dataBits; }
                set { dataBits = value; }
            }
            string portName;
            public string PortName
            {
                get { return portName; }
                set { portName = value; }
            }
        }

        //-----------------------------------
        // Command method
        //-----------------------------------

        public override string getName()
        {
            return this.GetType().ToString();
        }
        public override bool InitCom(string sPortName, int iBaudRate, int iDataBits, out string msg)
        {
            msg = "";
            icom.PortName = sPortName;
            icom.BaudRate = iBaudRate;
            icom.DataBits = iDataBits;

            if (CheckPortNameIsValid() == true &&
                CheckBaudRateIsValid() == true &&
                CheckDataBitsIsValid() == true)
            {
                port = new SerialPort(icom.PortName, icom.BaudRate, Parity.None, icom.DataBits, StopBits.One);
                msg = "Com Port Init is valid.";
                return true;
            }
            else
            {
                msg = "Com Port Init is invalid.";
                return false;
            }
        }
        private bool CheckPortNameIsValid()
        {
            if (icom.PortName != "" && icom.PortName != null && icom.PortName.Contains("Com") == true)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        private bool CheckBaudRateIsValid()
        {
            if (icom.BaudRate >= 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        private bool CheckDataBitsIsValid()
        {
            if (icom.DataBits >= 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public void checkComState()
        {
            if (!getPort().IsOpen)
            {
                openCom();
            }
            else
            {
                //this com is open,that let it doing.
            }
        }
        public bool getComState()
        {
            if (port.IsOpen)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 反复初始化com，会出现2个com实例对象去控制1个com口的资源同步问题。
        /// 因为当A正与com1通讯时，B也要跟com1通讯，这时只有让大家挨个的跟com1通讯
        /// （A<->com1 完毕，B<->com1），才不会出现com1口被xx占用的资源同步问题。
        /// </summary>
        /// <returns></returns>
        public bool CheckComWhetherInitialization()
        {
            bool result = false;

            if (icom.PortName == null || icom.BaudRate == 0 || icom.DataBits == 0)
            {
                result = false;
            }
            else
            {
                result = true;
            }

            return result;
        }
        private SerialPort getPort()
        {
            return port;
        }
        public override bool openCom()
        {
            try
            {
                port.Open();

                return true;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }

        }
        public override bool closeCom()
        {
            try
            {
                port.Close();

                return true;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }
        public override bool sendCommand(string arg)
        {
            checkComState();

            byte[] content = getCommandContent(arg);

            setSendCommandContent(content);

            if (content != null)
            {                
                port.Write(content, 0, content.Length);

                DisplayCommandInformationInRichBox("发送指令成功！", HexAdecimalToString(getSendCommandContent()));

                return true;
            }
            else
            {
                DisplayCommandInformationInRichBox("发送指令失败！", HexAdecimalToString(getSendCommandContent()));

                return false;
            }
        }
        public override bool receiveCommand()
        {
            checkComState();

            Thread.Sleep(200);

            byte[] buf = new byte[port.BytesToRead];

            port.Read(buf, 0, port.BytesToRead);

            setReceiveCommandContent(buf);

            if (getReceiveCommandContent().Length != 0)
            {
                if (CompareCommand(getSendCommandContent(), getReceiveCommandContent()) == true)
                {
                    DisplayCommandInformationInRichBox("返回指令成功！", HexAdecimalToString(getReceiveCommandContent()));

                    return true;
                }
                else
                {
                    DisplayCommandInformationInRichBox("返回指令失败！", HexAdecimalToString(getReceiveCommandContent()));

                    return false;
                }
            }
            else
            {
                DisplayCommandInformationInRichBox("返回指令失败！", HexAdecimalToString(getReceiveCommandContent()));

                return false;
            }

        }
        private void setSendCommandContent(byte[] arg)
        {
            this.sendCommandContent = arg;
        }
        private byte[] getSendCommandContent()
        {
            return this.sendCommandContent;
        }
        private void setReceiveCommandContent(byte[] arg)
        {
            this.receiveCommandContent = arg;
        }
        private byte[] getReceiveCommandContent()
        {
            return this.receiveCommandContent;
        }
        public override void ErgodiclstCommandContent()
        {
            openCom();
            foreach (string k in lstCommandContent.Keys)
            {
                sendCommand(k);
                receiveCommand();
                Thread.Sleep(50);
            }
            closeCom();
            DisplayCommandInformationInOneLineWithOnlyOneTitle("prass any key, to continuse.");
            Console.ReadLine();
        }

        //-----------------------------------
        //1 - data type conversion.
        //2 - check command.
        //3 - display receive / send command information
        //-----------------------------------

        private bool CompareCommand(byte[] send, byte[] receive)
        {
            if (HexAdecimalToString(send) == HexAdecimalToString(receive))
            {
                return true;
            }
            else
            {
                return false;
            }

        }
        private bool CompareCommand(string send, string receive)
        {
            if (send == receive)
            {
                return true;
            }
            else
            {
                return false;
            }

        }
        private bool CompareCommand(int send, int receive)
        {
            return false;
        }
        private string HexAdecimalToString(byte[] arg)
        {
            string result = "";
            string fill_a = "0";

            if (arg != null)
            {
                foreach (byte a in arg)
                {
                    if (Convert.ToString(a, 16).Length == 1)
                    {
                        result += fill_a + Convert.ToString(a, 16) + " ";
                    }
                    else
                    {
                        result += Convert.ToString(a, 16) + " ";
                    }
                }

                return result;
            }
            else
            {
                return "";
            }

        }
        private int HexAdecimalToInt(byte[] arg)
        {
            return 0;
        }
        private ListBox _lb;
        public void SetListBox(ListBox lb)
        {
            this._lb = lb;
        }
        public ListBox GetListBox()
        {
            try
            {
                return this._lb;
            }
            catch (System.NullReferenceException ex)
            {
                MessageBox.Show(ex.Message);

                return null;
            }

        }
        private void DisplayCommandInformationInListBox(string title, string command)
        {
            GetListBox().Items.Add("==========================");
            GetListBox().Items.Add(DateTime.Now.ToLocalTime().ToString());
            GetListBox().Items.Add("==========================");
            GetListBox().Items.Add(title);
            GetListBox().Items.Add(command);
            GetListBox().Items.Add(Environment.NewLine);

            //其实就是当添加了项目以后自动选种最后的项目。它就会自己往下滚了。
            //1 - 以添加的内容在ListBox中的名称来确定ListBox的scrollBar的位置            
            //GetListBox().SelectedItem = GetListBox().Items[GetListBox().Items.Count - 1];
            //2 - 以添加的内容在ListBox中的队序号来确定ListBox的scrollBar的位置
            GetListBox().SelectedIndex = GetListBox().Items.Count - 1;

        }
        private RichTextBox _rtb;
        public void SetRichTextBox(RichTextBox rtb)
        {
            this._rtb = rtb;
        }
        public RichTextBox GetRichTextBox()
        {
            try
            {
                return this._rtb;
            }
            catch (System.NullReferenceException ex)
            {
                MessageBox.Show(ex.Message);

                return null;
            }

        }
        public void DisplayCommandInformationInRichBox(string title, string command)
        {
            GetRichTextBox().Text +=
                "==========================" +
                Environment.NewLine +
                DateTime.Now.ToLocalTime().ToString() +
                Environment.NewLine +
                "==========================" +
                Environment.NewLine +
                title + Environment.NewLine +
                command + Environment.NewLine +
                Environment.NewLine;

            GetRichTextBox().SelectionStart = GetRichTextBox().TextLength;
            GetRichTextBox().ScrollToCaret();
        }
        private void DisplayCommandInformation(string title, string command)
        {
            Console.WriteLine("==========================");
            Console.WriteLine(DateTime.Now.ToLocalTime());
            Console.WriteLine("==========================");
            Console.WriteLine(title);
            Console.WriteLine(command);
            Console.WriteLine(Environment.NewLine);
        }
        private void DisplayCommandInformationInOneLine(string title, string arg)
        {
            Console.WriteLine(title, arg);
        }
        private void DisplayCommandInformationInOneLineWithOnlyOneTitle(string title)
        {
            Console.WriteLine(title);
        }

        //-----------------------------------
        //ePRLU Command lists
        //-----------------------------------
        private IDictionary<string, byte[]> lstCommandContent = new Dictionary<string, byte[]>();

        byte[] CLOSE_ALL_PA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0x90, 0x5D, 0x2B, 0x7F };
        byte[] OPEN_CHANNEL1_PA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0x91, 0x4D, 0x0A, 0x7F };
        byte[] OPEN_CHANNEL2_PA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0x92, 0x7D, 0x69, 0x7F };
        byte[] OPEN_CHANNEL3_PA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0x93, 0x6D, 0x48, 0x7F };
        byte[] OPEN_CHANNEL4_PA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0x94, 0x1D, 0xAF, 0x7F };

        byte[] OPEN_CHANNEL5_PA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0x91, 0x4D, 0x0A, 0x7F };
        byte[] OPEN_CHANNEL6_PA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0x92, 0x7D, 0x69, 0x7F };
        byte[] OPEN_CHANNEL7_PA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0x93, 0x6D, 0x48, 0x7F };
        byte[] OPEN_CHANNEL8_PA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0x94, 0x1D, 0xAF, 0x7F };
        byte[] OPEN_ALL_PA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0x9F, 0xAC, 0xC4, 0x7F };

        byte[] CLOSE_ALL_CHANNEL_LNA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xA0, 0x6B, 0x78, 0x7F };
        byte[] OPEN_CHANNEL1_LNA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xA1, 0x7B, 0x59, 0x7F };
        byte[] OPEN_CHANNEL2_LNA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xA2, 0x4B, 0x3A, 0x7F };
        byte[] OPEN_CHANNEL3_LNA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xA3, 0x5B, 0x1B, 0x7F };
        byte[] OPEN_CHANNEL4_LNA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xA4, 0x2B, 0xFC, 0x7F };
        byte[] OPEN_CHANNEL5_LNA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xA1, 0x7B, 0x59, 0x7F };
        byte[] OPEN_CHANNEL6_LNA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xA2, 0x4B, 0x3A, 0x7F };
        byte[] OPEN_CHANNEL7_LNA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xA3, 0x5B, 0x1B, 0x7F };
        byte[] OPEN_CHANNEL8_LNA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xA4, 0x2B, 0xFC, 0x7F };
        byte[] OPEN_ALL_CHANNEL_LNA = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xAF, 0x9A, 0x97, 0x7F };

        //byte[] OPEN_CHANNEL1_FORWARD_POWER_CLOSE_TOHERS = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xB1, 0x69, 0x68, 0x7F };
        //byte[] OPEN_CHANNEL2_FORWARD_POWER_CLOSE_TOHERS = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xB2, 0x59, 0x0B, 0x7F };
        //byte[] OPEN_CHANNEL3_FORWARD_POWER_CLOSE_TOHERS = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xB3, 0x69, 0x68, 0x7F };
        //byte[] OPEN_CHANNEL4_FORWARD_POWER_CLOSE_TOHERS = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xB4, 0x59, 0x0B, 0x7F };

        //byte[] OPEN_CHANNEL1_REVERSE_POWER = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xC1, 0x17, 0xFF, 0x7F };
        //byte[] OPEN_CHANNEL2_REVERSE_POWER = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xC2, 0x27, 0x9C, 0x7F };
        //byte[] OPEN_CHANNEL3_REVERSE_POWER = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xC3, 0x17, 0xFF, 0x7F };
        //byte[] OPEN_CHANNEL4_REVERSE_POWER = { 0x7E, 0x01, 0x00, 0xD0, 0x00, 0x01, 0xC4, 0x27, 0x9C, 0x7F };

        private byte[] getCommandContent(string arg)
        {
            bool find = false;
            byte[] res = null;

            foreach (string keys in lstCommandContent.Keys)
            {
                if (arg == keys)
                {
                    find = true;

                    if (lstCommandContent.TryGetValue(keys, out res))
                    {
                        DisplayCommandInformationInOneLine("输入的指令：{0} 在指令库中找到。", arg);
                        return res;
                    }
                }
            }

            if (find == false)
            {
                DisplayCommandInformationInOneLine("输入的指令：{0} 在指令库中没有找到，请确认后继续。", arg);
                return null;
            }

            return res;

        }
        private void AppendCommandToDictionary()
        {
            Add("CLOSE_ALL_PA", CLOSE_ALL_PA).
            Add("OPEN_CHANNEL1_PA", OPEN_CHANNEL1_PA).
            Add("OPEN_CHANNEL2_PA", OPEN_CHANNEL2_PA).
            Add("OPEN_CHANNEL3_PA", OPEN_CHANNEL3_PA).
            Add("OPEN_CHANNEL4_PA", OPEN_CHANNEL4_PA).
            Add("OPEN_CHANNEL5_PA", OPEN_CHANNEL5_PA).
            Add("OPEN_CHANNEL6_PA", OPEN_CHANNEL6_PA).
            Add("OPEN_CHANNEL7_PA", OPEN_CHANNEL7_PA).
            Add("OPEN_CHANNEL8_PA", OPEN_CHANNEL8_PA).
            Add("OPEN_ALL_PA", OPEN_ALL_PA).
            Add("CLOSE_ALL_CHANNEL_LNA", CLOSE_ALL_CHANNEL_LNA).
            Add("OPEN_CHANNEL1_LNA", OPEN_CHANNEL1_LNA).
            Add("OPEN_CHANNEL2_LNA", OPEN_CHANNEL2_LNA).
            Add("OPEN_CHANNEL3_LNA", OPEN_CHANNEL3_LNA).
            Add("OPEN_CHANNEL4_LNA", OPEN_CHANNEL4_LNA).
            Add("OPEN_ALL_CHANNEL_LNA", OPEN_ALL_CHANNEL_LNA);//.
            //Add("OPEN_CHANNEL1_FORWARD_POWER_CLOSE_TOHERS", OPEN_CHANNEL1_FORWARD_POWER_CLOSE_TOHERS).
            //Add("OPEN_CHANNEL2_FORWARD_POWER_CLOSE_TOHERS", OPEN_CHANNEL2_FORWARD_POWER_CLOSE_TOHERS).
            //Add("OPEN_CHANNEL3_FORWARD_POWER_CLOSE_TOHERS", OPEN_CHANNEL3_FORWARD_POWER_CLOSE_TOHERS).
            //Add("OPEN_CHANNEL4_FORWARD_POWER_CLOSE_TOHERS", OPEN_CHANNEL4_FORWARD_POWER_CLOSE_TOHERS).
            //Add("OPEN_CHANNEL1_REVERSE_POWER", OPEN_CHANNEL1_REVERSE_POWER).
            //Add("OPEN_CHANNEL2_REVERSE_POWER", OPEN_CHANNEL2_REVERSE_POWER).
            //Add("OPEN_CHANNEL3_REVERSE_POWER", OPEN_CHANNEL3_REVERSE_POWER).
            //Add("OPEN_CHANNEL4_REVERSE_POWER", OPEN_CHANNEL4_REVERSE_POWER);
        }
        private TMR045 Add(string keys, byte[] content)
        {
            lstCommandContent.Add(keys, content);
            return this;
        }
        public byte[] getSpecialCommand(string arg)
        {
            byte[] result = null;

            foreach (string key in lstCommandContent.Keys)
            {
                if (key.Contains(arg) == true)
                {
                    lstCommandContent.TryGetValue(key, out result);
                    break;
                }
            }

            return result;
        }


        //-----------------------------------
        //calculator power efficient
        //-----------------------------------
        private double Current5Point5_FirstTime;
        public void SetCurrent5Point5_FirstTime(double arg)
        {            
            try
            {
                this.Current5Point5_FirstTime = arg;
            }
            catch (ArgumentNullException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        public double GetCurrent5Point5_FirstTime()
        {
            return this.Current5Point5_FirstTime;
        }

        private double Current5Point5_SecondTime;
        public void SetCurrent5Point5_SecondTime(double arg)
        {
            try
            {
                this.Current5Point5_SecondTime = arg;
            }
            catch (ArgumentNullException ex)
            {
                MessageBox.Show(ex.Message);
            }
            
        }
        public double GetCurrent5Point5_SecondTime()
        {
            return this.Current5Point5_SecondTime;
        }

        private double Current28_FirstTime;
        public void SetCurrent28_FirstTime(double arg)
        {
            try
            {
                this.Current28_FirstTime = arg;
            }
            catch (ArgumentNullException ex)
            {
                MessageBox.Show(ex.Message);
            }
            
        }
        public double GetCurrent28_FirstTime()
        {
            return this.Current28_FirstTime;
        }

        private double Current28_SecondTime;
        public void SetCurrent28_SecondTime(double arg)
        {
            try
            {
                this.Current28_SecondTime = arg;
            }
            catch (ArgumentNullException ex)
            {
                MessageBox.Show(ex.Message);
            }
            
        }
        public double GetCurrent28_SecondTime()
        {
            return this.Current28_SecondTime;
        }


        public double CalculatorPowerEfficient()
        {
            //10/(5.5* I5.5+28*I28V-5.5* II5.5-28*II28V)*100%;
            double result = (5.7 * GetCurrent5Point5_FirstTime()
                + 28.5 * GetCurrent28_FirstTime()
                - 5.7 * GetCurrent5Point5_SecondTime()
                - 28.5 * GetCurrent28_SecondTime());
            result = 10 / result;

            return result;
        }



























    }
}
